package com.tencent.wxcloudrun.service.business;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tencent.wxcloudrun.config.RedisLock;
import com.tencent.wxcloudrun.pojo.bo.NoticeConstant;
import com.tencent.wxcloudrun.pojo.bo.NoticeStateEnum;
import com.tencent.wxcloudrun.pojo.po.XApplyLand;
import com.tencent.wxcloudrun.pojo.po.XHouseAuthMiddle;
import com.tencent.wxcloudrun.pojo.po.XHouseInfo;
import com.tencent.wxcloudrun.pojo.po.XNoticeManage;
import com.tencent.wxcloudrun.service.XApplyLandService;
import com.tencent.wxcloudrun.service.XHouseAuthMiddleService;
import com.tencent.wxcloudrun.service.XHouseInfoService;
import com.tencent.wxcloudrun.service.XNoticeManageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Slf4j
@Component
public class TimerService {

    // 每天0点01分执行一次
    private static final String AT_00_01 = "0 1 0 * * ?";
    // 每天0点30分执行一次
    private static final String AT_00_30 = "0 30 0 * * ?";
    @Resource
    private XNoticeManageService xNoticeManageService;
    @Resource
    private XApplyLandService xApplyLandService;
    @Resource
    private XHouseAuthMiddleService xHouseAuthMiddleService;
    @Resource
    private XHouseInfoService xHouseInfoService;
    @Resource
    private NoticeService noticeService;

    /**
     * 1、每天凌晨开始时执行，用户申请成为房东，两周内未处理的房东申请，可以参考ManageService类中的 dealFailApply 方法，
     * 涉及到的表是 x_apply_land ，将其置为审批失败状态，然后给申请者用房东身份发一个通知信息，
     * 就说您的房东申请超过两周未处理，可以重新发起申请。
     */
    @Scheduled(cron = AT_00_01)
    @Async("threadPoolForTimer")
    @RedisLock(prefix = "dealFangdongPower_TimeJob")
    public void dealFangdongPower() {
        log.info("开始执行房东申请超时处理任务 - 线程：{}", Thread.currentThread().getName());

        try {
            // 计算两周前的时间
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_MONTH, -14);
            Date twoWeeksAgo = calendar.getTime();

            // 查询两周前提交且状态为待审批（状态为1）的房东申请
            LambdaQueryWrapper<XApplyLand> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(XApplyLand::getStatus, "1")  // 审批中状态
                    .lt(XApplyLand::getCreateTime, twoWeeksAgo);

            List<XApplyLand> expiredApplyList = xApplyLandService.list(queryWrapper);

            if (expiredApplyList.isEmpty()) {
                log.info("房东申请超时处理任务完成 - 无需处理的数据");
                return;
            }

            int successCount = 0;
            int failCount = 0;

            for (XApplyLand applyLand : expiredApplyList) {
                try {
                    // 更新申请状态为审批失败
                    XApplyLand updateApply = new XApplyLand();
                    updateApply.setId(applyLand.getId());
                    updateApply.setStatus("2");  // 审批失败状态
                    updateApply.setFailInfo("您的房东申请超过两周未处理，系统已自动设置为失败状态，您可以重新发起申请。");
                    updateApply.setUpdateTime(new Date());

                    boolean updateResult = xApplyLandService.updateById(updateApply);

                    if (updateResult) {
                        // 发送通知给申请者
                        try {
                            noticeService.createNoticeByOpenid(
                                    applyLand.getOpenId(),
                                    "land",
                                    String.format(NoticeConstant.LAND_APPROVE_TITLE, "超时失败"),
                                    "您的房东申请超过两周未处理，系统已自动设置为失败状态。您可以重新发起申请，感谢您的理解。"
                            );
                            successCount++;
                            log.info("成功处理房东申请超时数据 - 申请者OpenId: {}, 申请ID: {}",
                                    applyLand.getOpenId(), applyLand.getApplyId());
                        } catch (Exception noticeException) {
                            log.error("处理房东申请超时数据成功，但发送通知失败 - 申请者OpenId: {}, 错误: {}",
                                    applyLand.getOpenId(), noticeException.getMessage());
                            successCount++;  // 仍然算作成功，只是通知发送失败
                        }
                    } else {
                        failCount++;
                        log.error("更新房东申请状态失败 - 申请者OpenId: {}, 申请ID: {}",
                                applyLand.getOpenId(), applyLand.getApplyId());
                    }

                } catch (Exception e) {
                    failCount++;
                    log.error("处理房东申请超时数据异常 - 申请者OpenId: {}, 错误: {}",
                            applyLand.getOpenId(), e.getMessage(), e);
                }
            }

            log.info("房东申请超时处理任务完成 - 总共处理 {} 条数据，成功 {} 条，失败 {} 条",
                    expiredApplyList.size(), successCount, failCount);

        } catch (Exception e) {
            log.error("房东申请超时处理任务执行异常：{}", e.getMessage(), e);
        }
    }

    /**
     * 2、每天凌晨一点钟开始处理，处于用户房屋认证的过期数据，涉及到的表是 x_house_auth_middle，首先发起时间超过两周的数据直接删除，然后
     * 这个表中有一个house_list字段，这个字段里面，存的是List<String> 类型的一个JSON串，里面的每一个具体的元素值对应的是 x_house_info 表的house_id字段
     * 那么就可以联表查询出这个房屋ID，对应的房屋的认证状态，也就是x_house_info表中的 pic_auth 字段，这个字段可能为空，或者为字符串 no   或者 yes
     * 只有为 yes是表示这个房屋是经过官方认证了的，然后除了前面的直接删除逻辑，还要检查处理，如果x_house_auth_middle表中的某条认证数据中涉及到的房屋都已经是认证为yes了，
     * 则这条数据也要删除。
     */
    @Scheduled(cron = "0 0 1 * * ?")  // 每天凌晨1点执行
    @Async("threadPoolForTimer")
    @RedisLock(prefix = "cleanHouseAuthData_TimeJob")
    public void cleanHouseAuthData() {
        log.info("开始执行房屋认证过期数据清理任务 - 线程：{}", Thread.currentThread().getName());

        try {
            // 计算两周前的时间
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_MONTH, -14);
            Date twoWeeksAgo = calendar.getTime();

            int totalDeleted = 0;

            // 1. 首先删除发起时间超过两周的数据
            LambdaQueryWrapper<XHouseAuthMiddle> expiredQueryWrapper = new LambdaQueryWrapper<>();
            expiredQueryWrapper.lt(XHouseAuthMiddle::getCreateTime, twoWeeksAgo);

            List<XHouseAuthMiddle> expiredList = xHouseAuthMiddleService.list(expiredQueryWrapper);
            if (!expiredList.isEmpty()) {
                boolean expiredDeleteResult = xHouseAuthMiddleService.remove(expiredQueryWrapper);
                if (expiredDeleteResult) {
                    totalDeleted += expiredList.size();
                    log.info("清理超过两周的房屋认证数据 - 成功清理 {} 条", expiredList.size());
                } else {
                    log.error("清理超过两周的房屋认证数据失败");
                }
            }

            // 2. 检查剩余数据中房屋都已认证完成的数据并删除
            List<XHouseAuthMiddle> remainingList = xHouseAuthMiddleService.list();

            for (XHouseAuthMiddle authMiddle : remainingList) {
                try {
                    // 解析房屋列表
                    List<String> houseIdList = JSON.parseArray(authMiddle.getHouseList(), String.class);

                    if (houseIdList == null || houseIdList.isEmpty()) {
                        // 如果房屋列表为空，直接删除这条记录
                        xHouseAuthMiddleService.removeById(authMiddle.getAuthId());
                        totalDeleted++;
                        log.info("删除空房屋列表的认证记录 - AuthId: {}", authMiddle.getAuthId());
                        continue;
                    }

                    // 查询这些房屋的认证状态
                    LambdaQueryWrapper<XHouseInfo> houseQueryWrapper = new LambdaQueryWrapper<>();
                    houseQueryWrapper.in(XHouseInfo::getHouseId, houseIdList);
                    List<XHouseInfo> houseInfoList = xHouseInfoService.list(houseQueryWrapper);

                    // 检查是否所有房屋都已认证
                    boolean allAuthenticated = true;
                    for (String houseId : houseIdList) {
                        boolean houseAuthenticated = false;
                        for (XHouseInfo houseInfo : houseInfoList) {
                            if (houseId.equals(houseInfo.getHouseId())) {
                                if ("yes".equals(houseInfo.getPicAuth())) {
                                    houseAuthenticated = true;
                                }
                                break;
                            }
                        }

                        if (!houseAuthenticated) {
                            allAuthenticated = false;
                            break;
                        }
                    }

                    // 如果所有房屋都已认证，删除这条认证记录
                    if (allAuthenticated) {
                        boolean deleteResult = xHouseAuthMiddleService.removeById(authMiddle.getAuthId());
                        if (deleteResult) {
                            totalDeleted++;
                            log.info("删除所有房屋已认证完成的认证记录 - AuthId: {}, 房东: {}",
                                    authMiddle.getAuthId(), authMiddle.getLandName());
                        } else {
                            log.error("删除已完成认证记录失败 - AuthId: {}", authMiddle.getAuthId());
                        }
                    }

                } catch (Exception e) {
                    log.error("处理房屋认证记录异常 - AuthId: {}, 错误: {}",
                            authMiddle.getAuthId(), e.getMessage(), e);
                }
            }

            if (totalDeleted > 0) {
                log.info("房屋认证过期数据清理任务完成 - 总共成功清理 {} 条数据", totalDeleted);
            } else {
                log.info("房屋认证过期数据清理任务完成 - 无需清理的数据");
            }

        } catch (Exception e) {
            log.error("房屋认证过期数据清理任务执行异常：{}", e.getMessage(), e);
        }
    }

    /**
     * 3、清理通知管理表数据，删除通知状态不为2（待处理）且创建时间已超过5天的数据，状态为2（待处理）且创建时间已超过7天的数据；
     */
    @Scheduled(cron = AT_00_30)
    @Async("threadPoolForTimer")
    @RedisLock(prefix = "cleanNoticeData_TimeJob")
    public void cleanNoticeData() {
        log.info("开始执行通知数据清理任务 - 线程：{}", Thread.currentThread().getName());

        try {
            // 计算5天前的时间
            Calendar calendar5Days = Calendar.getInstance();
            calendar5Days.add(Calendar.DAY_OF_MONTH, -5);
            Date fiveDaysAgo = calendar5Days.getTime();

            // 计算7天前的时间
            Calendar calendar7Days = Calendar.getInstance();
            calendar7Days.add(Calendar.DAY_OF_MONTH, -7);
            Date sevenDaysAgo = calendar7Days.getTime();

            int totalDeleted = 0;

            // 清理状态不为2且创建时间超过5天的数据
            LambdaQueryWrapper<XNoticeManage> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.ne(XNoticeManage::getNoticeState, NoticeStateEnum.TWO.getKey())
                    .lt(XNoticeManage::getCreateTime, fiveDaysAgo);

            List<XNoticeManage> toDeleteList1 = xNoticeManageService.list(queryWrapper1);
            if (!toDeleteList1.isEmpty()) {
                boolean deleteResult1 = xNoticeManageService.remove(queryWrapper1);
                if (deleteResult1) {
                    totalDeleted += toDeleteList1.size();
                    log.info("清理非待处理状态且超过5天的数据 - 成功清理 {} 条", toDeleteList1.size());
                } else {
                    log.error("清理非待处理状态且超过5天的数据失败");
                }
            }

            // 清理状态为2且创建时间超过7天的数据
            LambdaQueryWrapper<XNoticeManage> queryWrapper2 = new LambdaQueryWrapper<>();
            queryWrapper2.eq(XNoticeManage::getNoticeState, NoticeStateEnum.TWO.getKey())
                    .lt(XNoticeManage::getCreateTime, sevenDaysAgo);

            List<XNoticeManage> toDeleteList2 = xNoticeManageService.list(queryWrapper2);
            if (!toDeleteList2.isEmpty()) {
                boolean deleteResult2 = xNoticeManageService.remove(queryWrapper2);
                if (deleteResult2) {
                    totalDeleted += toDeleteList2.size();
                    log.info("清理待处理状态且超过7天的数据 - 成功清理 {} 条", toDeleteList2.size());
                } else {
                    log.error("清理待处理状态且超过7天的数据失败");
                }
            }

            if (totalDeleted > 0) {
                log.info("通知数据清理任务完成 - 总共成功清理 {} 条数据", totalDeleted);
            } else {
                log.info("通知数据清理任务完成 - 无需清理的数据");
            }

        } catch (Exception e) {
            log.error("通知数据清理任务执行异常：{}", e.getMessage(), e);
        }
    }
}
